﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using smsclictr.automation;
using Microsoft.SystemCenter.Orchestrator.Integration;
using System.Management;


namespace OpalisAddOn.Updates
{
    /// <summary>
    /// Re-Deploy Security Updates (Re-Evaluation)
    /// </summary>
    [Activity("Update Deployment", Description="Deploy authorized Software updates...")]
    public class UpdateDeploy
    {
        private String targetComputer;
        private String userName;
        private string password;

        [ActivityInput]
        public String TargetComputer
        {
            set { targetComputer = value; }
        }

        [ActivityInput(Optional = true)]
        public String UserName
        {
            set { userName = value; }
        }

        [ActivityInput(Optional = true, PasswordProtected = true)]
        public String Password
        {
            set { password = value; }
        }


        [ActivityMethod]
        public void Invoke()
        {
            SMSClient oClient;
            if (string.IsNullOrEmpty(userName))
            {
                oClient = new SMSClient(targetComputer);
            }
            else
            {
                oClient = new SMSClient(targetComputer, userName, password);
            }

            oClient.Schedules.UpdatesSourceStore();
            oClient.Schedules.UpdateAssignmentEval();
        }
    }

    /// <summary>
    /// Scan for Security Updates
    /// </summary>
    [Activity("Update Scan", Description="Scan for missing software updates...")]
    public class UpdateScan
    {
        private String targetComputer;
        private String userName;
        private string password;

        [ActivityInput]
        public String TargetComputer
        {
            set { targetComputer = value; }
        }

        [ActivityInput(Optional = true)]
        public String UserName
        {
            set { userName = value; }
        }

        [ActivityInput(Optional = true, PasswordProtected = true)]
        public String Password
        {
            set { password = value; }
        }

        [ActivityMethod]
        public void Invoke()
        {
            SMSClient oClient;
            if (string.IsNullOrEmpty(userName))
            {
                oClient = new SMSClient(targetComputer);
            }
            else
            {
                oClient = new SMSClient(targetComputer, userName, password);
            }

            oClient.Schedules.UpdatesSourceScan();
        }
    }

    /// <summary>
    /// Check if Pacth-Reboot is pending
    /// </summary>
    [Activity("WUA Reboot Pending", Description="Check if a reboot is pending beacuse of installed security patches")]
    public class WUAReboot
    {
        private String targetComputer;
        private String userName;
        private string password;
        private Boolean rebootPending;

        [ActivityInput]
        public String TargetComputer
        {
            set { targetComputer = value; }
        }

        [ActivityInput(Optional = true)]
        public String UserName
        {
            set { userName = value; }
        }

        [ActivityInput(Optional = true, PasswordProtected = true)]
        public String Password
        {
            set { password = value; }
        }

        [ActivityOutput("Reboot Pending", Description = "True = A Reboot is required")]
        public Boolean RebootPending
        {
            get { return rebootPending; }
        }

        [ActivityMethod]
        public void Invoke()
        {
            SMSClient oClient;
            if (string.IsNullOrEmpty(userName))
            {
                oClient = new SMSClient(targetComputer);
            }
            else
            {
                oClient = new SMSClient(targetComputer, userName, password);
            }

            rebootPending = false;
            try
            {
                ManagementScope myScope = oClient.Connection.mScope.Clone();

                if (oClient.ComputerSystem.isX64)
                {
                    myScope.Options.Context.Add("__ProviderArchitecture", 64);
                    myScope.Options.Context.Add("__RequiredArchitecture", true);
                }

                WMIRegistry oReg = new WMIRegistry(new WMIProvider(myScope));
                List<string> aList = new List<string>();

                aList = oReg.RegValuesList(2147483650, @"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired");
                
                foreach (string sValue in aList)
                {
                    if (int.Parse(oReg.GetDWord(2147483650, @"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired", sValue)) > 0)
                    {
                        rebootPending = true;
                        break;
                    }
                }
            }
            catch { }

        }
    }

    /// <summary>
    /// Check if File-Rename Operation is pending
    /// </summary>
    [Activity("File rename operation pending", Description="Check if file rename operations are pending...")]
    public class FileRename
    {
        private String targetComputer;
        private String userName;
        private string password;
        private Boolean renamePending;

        [ActivityInput]
        public String TargetComputer
        {
            set { targetComputer = value; }
        }

        [ActivityInput(Optional = true)]
        public String UserName
        {
            set { userName = value; }
        }

        [ActivityInput(Optional = true, PasswordProtected = true)]
        public String Password
        {
            set { password = value; }
        }

        [ActivityOutput("Rename Pending", Description = "True = File rename operation is pending")]
        public Boolean RenamePending
        {
            get { return renamePending; }
        }

        [ActivityMethod]
        public void Invoke()
        {
            SMSClient oClient;
            if (string.IsNullOrEmpty(userName))
            {
                oClient = new SMSClient(targetComputer);
            }
            else
            {
                oClient = new SMSClient(targetComputer, userName, password);
            }

            renamePending = false;
            WMIRegistry oReg = new WMIRegistry(new WMIProvider(oClient.Connection.mScope));
            string[] sPendingFileRename = oReg.GetMultiString(2147483650, @"SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations", "");

            if (!string.IsNullOrEmpty(sPendingFileRename[0]))
            {
                renamePending = true;
            }


        }
    }

    /// <summary>
    /// Check missing security updates
    /// </summary>
    [Activity("Missing Security Updates", Description="Check for missing authorized security patches...")]
    public class MissingPatches
    {
        private String targetComputer;
        private String userName;
        private string password;
        private List<string> missingArticles;
        private List<string> missingUpdateIDs;
        private Boolean patchesMissing;

        [ActivityInput]
        public String TargetComputer
        {
            set { targetComputer = value; }
        }

        [ActivityInput(Optional = true)]
        public String UserName
        {
            set { userName = value; }
        }

        [ActivityInput(Optional = true, PasswordProtected = true)]
        public String Password
        {
            set { password = value; }
        }

        [ActivityOutput("Patch Missing", Description = "True = Approved Patches are missing")]
        public Boolean PatchesMissing
        {
            get { return patchesMissing; }
        }

        [ActivityOutput("Missing patches...", Description = "List of missing Articles")]
        public List<string> MissingArticles
        {
            get { return missingArticles; }
        }

        [ActivityOutput("Missing UpdateIDs...", Description = "List of missing UpdateIDs")]
        public List<string> MissingUpdateIDs
        {
            get { return missingUpdateIDs; }
        }

        [ActivityMethod]
        public void Invoke()
        {
            SMSClient oClient;
            if (string.IsNullOrEmpty(userName))
            {
                oClient = new SMSClient(targetComputer);
            }
            else
            {
                oClient = new SMSClient(targetComputer, userName, password);
            }

            List<string> ApprovedUpdateIDs = new List<string>();
            missingArticles = new List<string>();
            missingUpdateIDs = new List<string>();
            
            ApprovedUpdateIDs = oClient.ApprovedUpdateIDs;
            patchesMissing = false;

            WMIProvider oWMIProv = new WMIProvider(oClient.Connection.mScope.Clone());
            oWMIProv.mScope.Path.NamespacePath = @"ROOT\ccm\SoftwareUpdates\UpdatesStore";
            foreach (ManagementObject MO in oWMIProv.GetClass("CCM_UpdateStatus").GetInstances())
            {
                string sArticle = MO.GetPropertyValue("Article").ToString();
                string sStatus = MO.GetPropertyValue("Status").ToString();
                string sRevision = MO.GetPropertyValue("RevisionNumber").ToString();
                string sSourceID = MO.GetPropertyValue("SourceUniqueId").ToString();
                string sBulletin = MO.GetPropertyValue("Bulletin").ToString();
                string sTitle = MO.GetPropertyValue("Title").ToString();
                string sUpdateID = MO.GetPropertyValue("UniqueId").ToString();

                if (ApprovedUpdateIDs.Contains(sUpdateID))
                {
                    if (string.Compare(sStatus, "Missing", true) == 0)
                    {
                        missingArticles.Add(sArticle);
                        missingUpdateIDs.Add(sUpdateID);
                        patchesMissing = true;
                    }
                }

            }
        }
    }

}

